package com.lemon.play.goai.posjudge.util;

import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ArrayTools {
	public static <E> E deepClone(E array) {
		Class componentType=array.getClass().getComponentType();
		E newArray = (E) Array.newInstance(componentType,Array.getLength(array));
		for (int i = 0; i < Array.getLength(array); i++) {
			if (componentType.isArray()) {
				Array.set(newArray, i, ArrayTools
						.deepClone(Array.get(array, i)));
			}
			else if(componentType.isPrimitive()){
				Array.set(newArray, i, Array.get(array, i));
			}
			else {
				try {
					Method clone = Array.get(array, i).getClass().getMethod(
							"clone");
					Array.set(newArray, i, clone.invoke(Array.get(array, i)));
				} catch (NoSuchMethodException e) {
					Array.set(newArray, i, Array.get(array, i));
				} catch (SecurityException e) {
					throw e;
				} catch (IllegalArgumentException e) {
					throw e;
				} catch (IllegalAccessException e) {
					RuntimeException newException = new IllegalStateException(
							"IllegalAccessException happend,please check cause!");
					newException.initCause(e);
					throw newException;
				} catch (InvocationTargetException e) {
					RuntimeException newException = new IllegalStateException(
							"InvocationTargetException happend,please check cause!");
					newException.initCause(e);
					throw newException;
				}
			}
		}
		return newArray;
	}
	
	public static <E extends Cloneable> void deepCopy(E[] src,int startSrc,E[] dest,int startDest,int length){
		if(startSrc<0)
			throw new IllegalArgumentException("Param startSrc cannot < 0");
		if(startDest<0)
			throw new IllegalArgumentException("Param startDest cannot < 0");
		if(length<=0)
			throw new IllegalArgumentException("Param length cannot <= 0");
		if(src==null)
			throw new IllegalArgumentException("Param src cannot be null");
		if(dest==null)
			throw new IllegalArgumentException("Param dest cannot be null");
		if(startSrc>=src.length)
			throw new IllegalArgumentException("Param startSrc cannot >= src.length");
		if(startDest>=dest.length)
			throw new IllegalArgumentException("Param startDest cannot >= dest.length");
		int copyLength=length;
		if(src.length-startSrc<copyLength)
			copyLength=src.length-startSrc;
		if(dest.length-startDest<copyLength)
			copyLength=dest.length-startDest;
		try {
			for (int i = 0; i < copyLength; i++) {
				Method clone = src[startSrc + i].getClass().getMethod("clone");
				dest[startDest + i] = (E) clone.invoke(src[startSrc + i]);
			}
		} catch (SecurityException e) {
			throw e;
		} catch (NoSuchMethodException e) {
			RuntimeException newException = new IllegalStateException(
					"NoSuchMethodException happend,please check cause!");
			newException.initCause(e);
			throw newException;
		} catch (IllegalArgumentException e) {
			throw e;
		} catch (IllegalAccessException e) {
			RuntimeException newException = new IllegalStateException(
					"IllegalAccessException happend,please check cause!");
			newException.initCause(e);
			throw newException;
		} catch (InvocationTargetException e) {
			RuntimeException newException = new IllegalStateException(
					"InvocationTargetException happend,please check cause!");
			newException.initCause(e);
			throw newException;
		}
	}
	
	public static <E> E[] growLength(E[] array){
		return growLength(array,10,0.2);
	}
	
	public static <E> E[] growLength(E[] array,int increase,double rate){
		int newLength=(int) (array.length+increase+array.length*rate);
		E[] newArray=(E[]) Array.newInstance(array.getClass().getComponentType(), newLength);
		System.arraycopy(array, 0, newArray, 0, array.length);
		return newArray;
	}

}
